﻿using IM.Easy.Core.Jobs;
using IM.Easy.Entity.Scheduled;
using IM.Easy.ScheduledServices.Dtos;
using Quartz;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace IM.Easy.ScheduledServices
{
    /// <summary>
    /// 扫描器实现
    /// </summary>
    public static class JobScanner
    {
        /// <summary>
        /// 扫描所有已加载程序集中符合要求的作业类
        /// </summary>
        public static List<JobOption> FindAllJobs()
        {
            return AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(assembly => GetLoadableTypes(assembly))
                .Where(IsConcreteJobType)
                .Select(CreateJobOption)
                .Where(job => job != null)
                .ToList();
        }

        /// <summary>
        /// 安全获取程序集中的所有可加载类型
        /// </summary>
        private static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
        {
            try
            {
                return assembly.GetTypes();
            }
            catch (ReflectionTypeLoadException ex)
            {
                return ex.Types.Where(t => t != null)!;
            }
            catch
            {
                return [];
            }
        }

        /// <summary>
        /// 验证是否为有效的具体作业类
        /// </summary>
        private static bool IsConcreteJobType(Type type)
        {
            var result = type is { IsAbstract: false } &&
                typeof(IJobDefinition).IsAssignableFrom(type);
            return result;
        }

        /// <summary>
        /// 创建作业的配置信息
        /// </summary>
        private static JobOption CreateJobOption(Type jobType)
        {
            return new JobOption
            {
                Name = GetJobName(jobType),
                JobType = jobType.AssemblyQualifiedName!
            };
        }

        /// <summary>
        /// 获取 `BaseJob` 子类的 `JobName`
        /// </summary>
        public static string GetJobName(Type jobType)
        {
            // 验证类型是否实现了 IJobDefinition 接口
            if (!typeof(IJobDefinition).IsAssignableFrom(jobType))
            {
                throw new ArgumentException($"类型 {jobType.Name} 未实现 IJobDefinition 接口");
            }

            // 获取静态属性 JobName 的信息
            PropertyInfo? property = jobType.GetProperty(
                nameof(IJobDefinition.JobName),
                BindingFlags.Public | BindingFlags.Static
            );

            // 检查属性是否存在且可读
            if (property == null || !property.CanRead)
            {
                throw new InvalidOperationException($"类型 {jobType.Name} 缺少可读的静态属性 {nameof(IJobDefinition.JobName)}");
            }

            // 获取属性值
            return (string)property.GetValue(null)!;
        }

    }
}
